#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   文件名称 :     pcb_event
   文件功能描述 :   功能描述
   创建人 :       小钟同学
   创建时间 :          2021/12/31
-------------------------------------------------
   修改描述-2021/12/31:
-------------------------------------------------
"""
from afast_core.core_libs.evnets_pcb import NameEventspace
from afast_core.core_plugins.pluginbase import IBasePlugin as BasePlugin
import typing
from fastapi import FastAPI


class PcbEvent:
    # 自定义全局的时间命名空间
    eventspace = NameEventspace()

    async def send_async_event(self, eventname, sender='ZYXEvent', **kwargs):
        '''
        有参的时候，需要传参，不能使用默认值，且需要此装饰器
        :param sender:
        :return:
        '''
        enent = self.eventspace
        # nonlocal enent

        if eventname and enent.has_receiver(eventname):
            pass
            ememt = enent.event(eventname)
            await ememt.send_async(sender, **kwargs)

    def send_sync_event(self, eventname, sender='ZYXEvent', **kwargs):
        '''
        有惨的时候，需要传参，不能使用默认值，且需要此装饰器
        :param sender:
        :return:
        '''
        enent = self.eventspace
        # nonlocal enent
        if eventname and enent.has_receiver(eventname):
            pass
            ememt = enent.event(eventname)
            ememt.send_sync(sender, **kwargs)

    def register_event(self, eventname: str, sender='ZYXEvent') -> typing.Callable:
        enent = self.eventspace

        def decorator(func: typing.Callable) -> typing.Callable:
            if eventname and not enent.has_receiver(eventname):
                ememt = enent.event(eventname)
                ememt.register_subscribe(func, sender)
            return func

        return decorator

    def add_register_event_handler(self, func: typing.Callable, eventname: str, sender='ZYXEvent',
                                   onlyonehandler=False) -> typing.Callable:
        '''
        允许重复注册多个处理器回调
        :param func:
        :param eventname:
        :param sender:
        :return:
        '''
        if eventname and onlyonehandler and not self.eventspace.has_receiver(eventname):
            # 如果只允许注册一个处理器对象的话就需要过滤避免多重注册
            ememt = self.eventspace.event(eventname)
            ememt.register_subscribe(func, sender)
        else:
            #  允许重复注册多个处理器回调
            ememt = self.eventspace.event(eventname)
            ememt.register_subscribe(func, sender)
        return func

    def before_request(self, func: typing.Callable, eventname: str = 'before_request',
                       sender='FastapiEvent') -> typing.Callable:

        ememt = self.eventspace.event(eventname)
        ememt.register_subscribe(func, sender)
        return func

    def after_request(self, func: typing.Callable, eventname: str = 'after_request',
                      sender='FastapiEvent') -> typing.Callable:

        ememt = self.eventspace.event(eventname)
        ememt.register_subscribe(func, sender)
        return func

    def teardown_appcontext(self, func: typing.Callable, eventname: str = 'teardown_appcontext',
                            sender='FastapiEvent') -> typing.Callable:

        ememt = self.eventspace.event(eventname)
        ememt.register_subscribe(func, sender)
        return func


class RequestPcbEventPluginClient(PcbEvent, BasePlugin):
    '''
    用法示例：

    core_app = FastAPI()

    rw = RequestPcbEvent(core_app=core_app,name='请求Hook事件插件')
    @rw.register_event(eventname='before_request',sender='FastapiEvent')
    async def wx_notify_third_inters_error1(sender, **kw):
        print("接收到了1！！！！！！！！！", sender, kw)

    @rw.before_request
    async def wx_notify_third_inters_error1(sender, **kw):
        print("接收到了3！！！！！！！！！", sender, kw)

    @rw.after_request
    async def wx_notify_third_inters_error1(sender, **kw):
        print("结束！！！！！！！！！", sender, kw)

    @core_app.event.after_request
    async def wx_notify_third_inters_error1(sender, **kw):
        print("结束2！！！！！！！！！", sender, kw)
    '''
    # 插件名称
    name = '请求Hook事件插件'

    def setup(self, app: FastAPI, name: str = None, *args, **kwargs):
        """插件初始化"""
        super().setup(app, name, *args, **kwargs)
        # 插件别名赋值到APP对象里面，让它持有该对象
        app.event_pcb = self

        # 业务逻辑初始化操作
        @app.middleware("http")
        async def log_request(request, call_next):
            response = None
            try:
                # 这里只发送定处理sender='FastapiEvent'，所以注册的时候需要注意
                await self.send_async_event(eventname='before_request', sender='FastapiEvent', request=request)
                response = await call_next(request)
                await self.send_async_event(eventname='after_request', sender='FastapiEvent', response=response)
                return response
            finally:
                pass
                await self.send_async_event(eventname='teardown_appcontext', sender='FastapiEvent', response=response)
